Set environment values (environments)

The environments view modifier allows injecting specific environment values into the current view hierarchy. It serves a role similar to SwiftUI’s .environment(), but with a more explicit and controlled design tailored for Scripting.

Currently, the modifier supports:

  • editMode — controls editing behavior in views such as List
  • openURL — customizes how links are handled when tapped

These environment values affect all descendants within the modified view subtree.


Modifier Definition

1environments?: {
2  editMode?: Observable<EditMode>;
3  openURL?: (url: string) => OpenURLActionResult;
4};

1. editMode Environment

The editMode environment value controls the editing state of views that support editing behavior, such as List with row deletion or movement.

It must be provided as an Observable<EditMode> so views can reactively update when the editing state changes.

EditMode Type

1class EditMode {
2  readonly value: "active" | "inactive" | "transient" | "unknown";
3  readonly isEditing: boolean;
4
5  static active(): EditMode;
6  static inactive(): EditMode;
7  static transient(): EditMode;
8}

Meaning of value

Value Description
active Editing mode is enabled
inactive Editing mode is disabled
transient Temporary transitional state
unknown Undefined or unexpected state

editMode Example

1const editMode = useObservable(() => EditMode.active())
2
3<List
4  environments={{
5    editMode: editMode
6  }}
7>
8  <ForEach
9    editActions="all"
10    data={items}
11    builder={item => <Text key={item.id}>{item}</Text>}
12  />
13</List>

2. openURL Environment

The openURL environment value customizes how URLs are handled when interacted with inside the view tree. It overrides the default behavior of components such as <Link>.

This is useful for:

  • Deciding whether URLs should open inside the app or externally
  • Filtering or validating URLs
  • Redirecting URLs to different handlers

Function Signature

1openURL?: (url: string) => OpenURLActionResult;

OpenURLActionResult

1class OpenURLActionResult {
2  type: string;
3
4  static handled(): OpenURLActionResult;
5  static discarded(): OpenURLActionResult;
6
7  static systemAction(options?: {
8    url?: string;
9    /**
10     * Whether the system should prefer opening the URL in-app.
11     * Requires iOS 26.0+.
12     */
13    prefersInApp: boolean;
14  }): OpenURLActionResult;
15}

Result Behavior

Method Meaning
handled() The URL is considered fully handled; default behavior stops
discarded() The URL is ignored
systemAction() Requests the system to open a (possibly modified) URL

iOS Requirement

  • prefersInApp requires iOS 26.0+
  • On earlier versions, the parameter may have no effect and system defaults will apply

openURL Example

1<Group
2  environments={{
3    openURL: (url) => {
4      return OpenURLActionResult.systemAction({
5        url,
6        prefersInApp: false   // Requires iOS 26.0+
7      })
8    }
9  }}
10>
11  {urls.map(url =>
12    <Link url={url}>{url}</Link>
13  )}
14</Group>

Combined Example (editMode + openURL)

1const editMode = useObservable(() => EditMode.inactive())
2
3<VStack
4  environments={{
5    editMode,
6    openURL: (url) => {
7      if (url.startsWith("https://safe.com")) {
8        return OpenURLActionResult.systemAction({
9          url,
10          prefersInApp: true   // iOS 26.0+ only
11        })
12      }
13      return OpenURLActionResult.discarded()
14    }
15  }}
16>
17  <Button
18    title="Toggle Edit"
19    action={() => {
20      editMode.value = editMode.value.isEditing
21        ? EditMode.inactive()
22        : EditMode.active()
23    }}
24  />
25
26  <List>
27    ...
28  </List>
29
30  <Link url="https://safe.com">Safe Link</Link>
31  <Link url="https://blocked.com">Blocked Link</Link>
32</VStack>

Notes & Behavior Summary

  1. The environments modifier applies only to the subtree where it is used.
  2. editMode must be an Observable<EditMode> for reactive updates.
  3. openURL replaces default URL-handling behavior for all descendant views.
  4. Returning handled() stops further URL processing.
  5. systemAction() delegates handling back to the system.
  6. prefersInApp requires iOS 26.0+ and may be ignored on earlier versions.
  7. Scripting’s environment system is explicit—only the values you define are injected.